#pragma once

#include "ccstd.hh"

namespace sirtet
{

struct Schedule
{
    using Step = std::function<bool(void *)>;
    using DeleteCallback = void (*)(void *);

  private:
    std::queue<Step> steps;
    void *user_data;
    DeleteCallback deleter;

  public:
    ~Schedule()
    {
        if (deleter != nullptr)
            deleter(user_data);
    }

    void tick()
    {
        if (steps.front()(user_data) == false)
        {
            steps.pop();
        }
    }

    bool completed()
    {
        return steps.size() <= 0;
    }

  public:
    struct Builder
    {
      private:
        std::queue<Step> steps;

      public:
        Builder &add_step(Step &&step)
        {
            steps.push(std::move(step));
            return *this;
        }

        Schedule build(void *user_data, DeleteCallback deleter = nullptr)
        {
            Schedule ret;
            ret.steps = std::move(steps);
            ret.user_data = user_data;
            ret.deleter = deleter;
            return ret;
        }
    };
};

} // namespace sirtet